#!/usr/bin/env python


import pprint
import re
import sys
import tempfile
import time


import tmux


class lazarus:

  def __init__(self, data):
    self.tmux = tmux.tmux()
    self.data = data

  def get_sessions(self):
    raw = self.tmux.list_sessions()
    lines = raw.split('\n')
    for line in lines:
      if line != '':
        name, size_x, size_y = line.split()
        self.data.add_session(name, size_x, size_y)

  def get_windows(self):
    for session in self.data.session_iter('latest-backup'):
      raw = self.tmux.list_windows(session)
      lines = raw.split('\n')
      for line in lines:
        if line != '':
          id, layout, name = line.split(' ', 2)
          self.data.add_window(session, id, name, layout)

  def get_panes(self):
    for session in self.data.session_iter('latest-backup'):
      for window in self.data.window_iter(session, 'latest-backup'):
        id = session + ':' + window
        raw = self.tmux.list_panes(id)
        lines = raw.split('\n')
        for line in lines:
          if line != '':
            pane, pid, pty = line.split()
            cwd = self.data.get_shell_cwd(pid)
            self.data.add_pane(
                session,
                window,
                pane,
                pid=pid,
                pty=pty,
                cwd=cwd,
                history=self.data.get_history(pid),
                screenshot=self.tmux.get_pane_screenshot(session + ':' + window + '.' + pane))

  def backup(self):
    self.data.start_new_backup()
    self.get_sessions()
    self.get_windows()
    self.get_panes()
    self.data.set_most_recent_backup_time()

  def restore(self, session_prefix):
    if self.tmux.currently_in_a_session():
      print >>sys.stderr, 'Restoring from within a tmux session not supported.'
      print >>sys.stderr, 'Detach and try again.'
      return
    base_index = None
    version = 'latest-backup'
    for session in self.data.session_iter(version):
      # Create session
      size_x = self.data.get_session_size_x(session, version)
      size_y = self.data.get_session_size_y(session, version)
      self.tmux.new_session(session_prefix + session, size_x, size_y)

      first_window = True
      for window in self.data.window_iter(session, version):
        window_id = session_prefix + session + ':' + window

        # Create windows
        window_name = self.data.get_window_name(session, window, version)
        if first_window:
          first_window = False
          to_window = session_prefix + session + ':' + str(window)
          if base_index is None:
            base_index = self.tmux.get_base_index()
          if base_index != window:
            from_window = session_prefix + session + ':' + str(base_index)
            self.tmux.move_window(from_window, to_window)
          self.tmux.rename_window(to_window, window_name)
        else:
          self.tmux.new_window(window_name, window_id)

        # Create panes
        panes = self.data.pane_iter(session, window, version)
        panes.next()  # Add n-1 panes -- the first is automatic
        for pane in panes:
          self.tmux.add_pane(window_id)

        # Set layout
        layout = self.data.get_window_layout(session, window, version)
        self.tmux.set_layout(window_id, layout)

        # Set up panes
        for pane in self.data.pane_iter(session, window, version):
          temp_file = tempfile.NamedTemporaryFile(delete=False)
          print >>temp_file, self.data.get_pane_history(session, window, pane, version)
          temp_file.close()
          pane_id = window_id + '.' + str(pane)
          cwd = self.data.get_pane_cwd(session, window, pane, version)
          self.tmux.send_keys(pane_id, ' cd ' + cwd)
          self.tmux.send_keys(pane_id, ' history -r ' + temp_file.name)
          self.tmux.send_keys(pane_id, ' rm -f ' + temp_file.name)
          self.tmux.send_keys(pane_id, ' clear')
          screenshot = self.data.get_pane_screenshot(session, window, pane, version)
          self.tmux.put_pane_screenshot(pane_id, screenshot)

  def save_history(self, pid, input=sys.stdin):
    if not self.tmux.currently_in_a_session():
      return

    # first line is CWD
    self.data.set_shell_cwd(pid, input.readline())

    # subsequent lines are history
    history_re = re.compile('''\s*\d+\*?\s+(.*)''')
    histlines = []
    line = input.readline()
    match = history_re.match(line)
    while line != "":
        histlines.append(match.group(1))

        # handle second and subsequent lines of multi-line entries
        line = input.readline()
        match = history_re.match(line)
        while line != "" and match is None:
            histlines.append(line.strip('\n'))
            line = input.readline()
            match = history_re.match(line)

    self.data.set_history(pid, '\n'.join(histlines))

  def dump(self):
    self.data.dump()

  def handle_command(self, options, args):
    command = args[0]
    if command == 'backup':
      self.backup()
    elif command == 'restore':
      self.restore(options.session_prefix)
    elif command == 'history':
      self.save_history(args[1])
    elif command == 'dump':
      self.dump()

